home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
patch
/
patch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-19
|
19KB
|
825 lines
char rcsid[] =
"$Header: patch.c,v 2.0.1.6 88/06/22 20:46:39 lwall Locked $";
/* patch - a program to apply diffs to original files
*
* Copyright 1986, Larry Wall
*
* This program may be copied as long as you don't try to make any
* money off of it, or pretend that you wrote it.
*
* $Log: patch.c,v $
* Revision 2.0.1.6 88/06/22 20:46:39 lwall
* patch12: rindex() wasn't declared
*
* Revision 2.0.1.5 88/06/03 15:09:37 lwall
* patch10: exit code improved.
* patch10: better support for non-flexfilenames.
*
* Revision 2.0.1.4 87/02/16 14:00:04 lwall
* Short replacement caused spurious "Out of sync" message.
*
* Revision 2.0.1.3 87/01/30 22:45:50 lwall
* Improved diagnostic on sync error.
* Moved do_ed_script() to pch.c.
*
* Revision 2.0.1.2 86/11/21 09:39:15 lwall
* Fuzz factor caused offset of installed lines.
*
* Revision 2.0.1.1 86/10/29 13:10:22 lwall
* Backwards search could terminate prematurely.
*
* Revision 2.0 86/09/17 15:37:32 lwall
* Baseline for netwide release.
*
* Revision 1.5 86/08/01 20:53:24 lwall
* Changed some %d's to %ld's.
* Linted.
*
* Revision 1.4 86/08/01 19:17:29 lwall
* Fixes for machines that can't vararg.
* Added fuzz factor.
* Generalized -p.
* General cleanup.
*
* 85/08/15 van%ucbmonet@berkeley
* Changes for 4.3bsd diff -c.
*
* Revision 1.3 85/03/26 15:07:43 lwall
* Frozen.
*
* Revision 1.2.1.9 85/03/12 17:03:35 lwall
* Changed pfp->_file to fileno(pfp).
*
* Revision 1.2.1.8 85/03/12 16:30:43 lwall
* Check i_ptr and i_womp to make sure they aren't null before freeing.
* Also allow ed output to be suppressed.
*
* Revision 1.2.1.7 85/03/12 15:56:13 lwall
* Added -p option from jromine@uci-750a.
*
* Revision 1.2.1.6 85/03/12 12:12:51 lwall
* Now checks for normalness of file to patch.
*
* Revision 1.2.1.5 85/03/12 11:52:12 lwall
* Added -D (#ifdef) option from joe@fluke.
*
* Revision 1.2.1.4 84/12/06 11:14:15 lwall
* Made smarter about SCCS subdirectories.
*
* Revision 1.2.1.3 84/12/05 11:18:43 lwall
* Added -l switch to do loose string comparison.
*
* Revision 1.2.1.2 84/12/04 09:47:13 lwall
* Failed hunk count not reset on multiple patch file.
*
* Revision 1.2.1.1 84/12/04 09:42:37 lwall
* Branch for sdcrdcf changes.
*
* Revision 1.2 84/11/29 13:29:51 lwall
* Linted. Identifiers uniqified. Fixed i_ptr malloc() bug. Fixed
* multiple calls to mktemp(). Will now work on machines that can only
* read 32767 chars. Added -R option for diffs with new and old swapped.
* Various cosmetic changes.
*
* Revision 1.1 84/11/09 17:03:58 lwall
* Initial revision
*
*/
#include "INTERN.h"
#include "common.h"
#include "EXTERN.h"
#include "version.h"
#include "util.h"
#include "pch.h"
#include "inp.h"
/* procedures */
void reinitialize_almost_everything();
void get_some_switches();
LINENUM locate_hunk();
void abort_hunk();
void apply_hunk();
void init_output();
void init_reject();
void copy_till();
void spew_output();
void dump_line();
bool patch_match();
bool similar();
void re_input();
void my_exit();
/* Apply a set of diffs as appropriate. */
main(argc,argv)
int argc;
char **argv;
{
LINENUM where;
LINENUM newwhere;
LINENUM fuzz;
LINENUM mymaxfuzz;
int hunk = 0;
int failed = 0;
int failtotal = 0;
int i;
setbuf(stderr, serrbuf);
for (i = 0; i<MAXFILEC; i++)
filearg[i] = Nullch;
Mktemp(TMPOUTNAME);
Mktemp(TMPINNAME);
Mktemp(TMPREJNAME);
Mktemp(TMPPATNAME);
/* parse switches */
Argc = argc;
Argv = argv;
get_some_switches();
/* make sure we clean up /tmp in case of disaster */
set_signals(0);
for (
open_patch_file(filearg[1]);
there_is_another_patch();
reinitialize_almost_everything()
) { /* for each patch in patch file */
if (outname == Nullch)
outname = savestr(filearg[0]);
/* initialize the patched file */
if (!skip_rest_of_patch)
init_output(TMPOUTNAME);
/* for ed script just up and do it and exit */
if (diff_type == ED_DIFF) {
do_ed_script();
continue;
}
/* initialize reject file */
init_reject(TMPREJNAME);
/* find out where all the lines are */
if (!skip_rest_of_patch)
scan_input(filearg[0]);
/* from here on, open no standard i/o files, because malloc */
/* might misfire and we can't catch it easily */
/* apply each hunk of patch */
hunk = 0;
failed = 0;
out_of_mem = FALSE;
while (another_hunk()) {
hunk++;
fuzz = Nulline;
mymaxfuzz = pch_context();
if (maxfuzz < mymaxfuzz)
mymaxfuzz = maxfuzz;
if (!skip_rest_of_patch) {
do {
where = locate_hunk(fuzz);
if (hunk == 1 && where == Nulline && !force) {
/* dwim for reversed patch? */
if (!pch_swap()) {
if (fuzz == Nulline)
say1(
"Not enough memory to try swapped hunk! Assuming unswapped.\n");
continue;
}
reverse = !reverse;
where = locate_hunk(fuzz); /* try again */
if (where == Nulline) { /* didn't find it swapped */
if (!pch_swap()) /* put it back to normal */
fatal1("Lost hunk on alloc error!\n");
reverse = !reverse;
}
else if (noreverse) {
if (!pch_swap()) /* put it back to normal */
fatal1("Lost hunk on alloc error!\n");
reverse = !reverse;
say1(
"Ignoring previously applied (or reversed) patch.\n");
skip_rest_of_patch = TRUE;
}
else {
ask3(
"%seversed (or previously applied) patch detected! %s -R? [y] ",
reverse ? "R" : "Unr",
reverse ? "Assume" : "Ignore");
if (*buf == 'n') {
ask1("Apply anyway? [n] ");
if (*buf != 'y')
skip_rest_of_patch = TRUE;
where = Nulline;
reverse = !reverse;
if (!pch_swap()) /* put it back to normal */
fatal1("Lost hunk on alloc error!\n");
}
}
}
} while (!skip_rest_of_patch && where == Nulline &&
++fuzz <= mymaxfuzz);
if (skip_rest_of_patch) { /* just got decided */
Fclose(ofp);
ofp = Nullfp;
}
}
newwhere = pch_newfirst() + last_offset;
if (skip_rest_of_patch) {
abort_hunk();
failed++;
if (verbose)
say3("Hunk #%d ignored at %ld.\n", hunk, newwhere);
}
else if (where == Nulline) {
abort_hunk();
failed++;
if (verbose)
say3("Hunk #%d failed at %ld.\n", hunk, newwhere);
}
else {
apply_hunk(where);
if (verbose) {
say3("Hunk #%d succeeded at %ld", hunk, newwhere);
if (fuzz)
say2(" with fuzz %ld", fuzz);
if (last_offset)
say3(" (offset %ld line%s)",
last_offset, last_offset==1L?"":"s");
say1(".\n");
}
}
}
if (out_of_mem && using_plan_a) {
Argc = Argc_last;
Argv = Argv_last;
say1("\n\nRan out of memory using Plan A--trying again...\n\n");
continue;
}
assert(hunk);
/* finish spewing out the new file */
if (!skip_rest_of_patch)
spew_output();
/* and put the output where desired */
ignore_signals();
if (!skip_rest_of_patch) {
if (move_file(TMPOUTNAME, outname) < 0) {
toutkeep = TRUE;
chmod(TMPOUTNAME, filemode);
}
else
chmod(outname, filemode);
}
Fclose(rejfp);
rejfp = Nullfp;
if (failed) {
failtotal += failed;
if (!*rejname) {
Strcpy(rejname, outname);
#ifndef FLEXFILENAMES
{
char *rindex();
char *s = rindex(rejname,'/');
if (!s)
s = rejname;
if (strlen(s) > 13)
if (s[12] == '.') /* try to preserve difference */
s[12] = s[13]; /* between .h, .c, .y, etc. */
s[13] = '\0';
}
#endif
Strcat(rejname, REJEXT);
}
if (skip_rest_of_patch) {
say4("%d out of %d hunks ignored--saving rejects to %s\n",
failed, hunk, rejname);
}
else {
say4("%d out of %d hunks failed--saving rejects to %s\n",
failed, hunk, rejname);
}
if (move_file(TMPREJNAME, rejname) < 0)
trejkeep = TRUE;
}
set_signals(1);
}
my_exit(failtotal);
}
/* Prepare to find the next patch to do in the patch file. */
void
reinitialize_almost_everything()
{
re_patch();
re_input();
input_lines = 0;